import { deepClone } from '@vue/devtools-shared';
import { useDebounceFn } from '@vueuse/core';
import { computed, ref } from 'vue';
import { ApiFn } from '~/packages/hooks/src';
import { useTable } from './table';

type Config = {
    columns: () => any[];
    apiFn: (data?: any) => Promise<any>;
    tableKey?: string;
    params?: any;
    immediate?: boolean;
    excludeColumns?: string[];
    extraColumns?: any[];
    customColumns?: any[];
    selection?: boolean;
    selectionDisabled?: (row: any) => boolean;
    summaryFn?: ApiFn;
    summaryColumns?: (summaryData: any) => any;
};

export function useDataTable(config?: Config) {
    // keyword input ref
    const inputRef = ref<HTMLInputElement>();

    // data-table ref
    const dataTableRef = ref<DataTable.TableRef>();

    // 激活当前行操作
    const curActiveRow = ref<any>();
    function getActiveRow() {
        return deepClone(curActiveRow.value) as any;
    }

    // 获取配置的列字段
    const configColumns = ref(config?.columns() || []);

    // 是否默认触发查询
    const immediate = config?.immediate === undefined ? true : config.immediate;

    // 动态 columns
    const dynamicColumns = computed<any>(() => {
        if (config?.customColumns) {
            return config.customColumns;
        }

        // 拷贝出一个新的数组
        const copyColumns = configColumns.value;

        // 是否可选
        if (config?.selection) {
            copyColumns.splice(0, 0, {
                type: 'selection',
                disabled: (row: any) =>
                    config?.selectionDisabled ? config!.selectionDisabled(row) : false
            });
        }

        // 额外 columns
        if (config?.extraColumns) {
            copyColumns.push(...config.extraColumns);
        }

        // 排除 columns key
        if (config?.excludeColumns) {
            return copyColumns.filter((item) => !config.excludeColumns!.includes(item.key));
        }

        return copyColumns;
    });

    // 构造默认请求参数
    const apiParams = ref<Record<string, any>>({
        keyword: '',
        page: {
            pageNumber: 1,
            pageSize: 50
        }
    });

    // 如果外有指定参数，那么进行覆盖赋值
    if (config?.params) {
        for (const [key] of Object.entries(config.params)) {
            apiParams.value[key] = config.params[key];
        }
    }

    // 实例化 Table 对象
    const dataTable = useTable({
        tableKey: config?.tableKey ? config!.tableKey : undefined,
        immediate,
        apiFn: config!.apiFn,
        summaryFn: config?.summaryFn,
        summaryColumns: (row: any) =>
            config?.summaryColumns ? config!.summaryColumns(row) : undefined,
        apiParams: apiParams.value,
        showTotal: true,
        columns: () => dynamicColumns.value
    });

    /**
     * 查询分页数据
     *
     * @param queryConfig 查询配置
     */
    async function getDataByPage(queryConfig?: {
        params?: any;
        reset?: boolean;
        active?: boolean;
        focus?: boolean;
    }) {
        // 更新查询参数
        if (queryConfig?.params) {
            dataTable.updateSearchParams(queryConfig.params);
        }

        // 触发查询
        await dataTable.getDataByPage();

        // 重置游标
        if (queryConfig?.reset) {
            dataTableRef.value?.resetCursor();
        }

        // 激活游标
        if (queryConfig?.active) {
            dataTableRef.value?.toActive();
        }

        // 激活输入框和表格行
        if (queryConfig?.focus) {
            inputRef.value?.focus();
            dataTableRef.value?.toActive();
        }
    }

    /** 重置查询参数 */
    function resetSearchParams() {
        dataTable.resetSearchParams();
    }

    // keyword 查询
    const queryKeywordHandler = (keyword: string) => {
        getDataByPage({
            params: {
                keyword,
                page: {
                    pageNumber: 1
                }
            }
        });
    };

    // 查询防抖
    const inputHandler = useDebounceFn(queryKeywordHandler, 300);

    // 提供方法给外部使用
    const methods = {
        dataTable,
        tableKey: config?.tableKey,
        getDataTableRef: () => dataTableRef,
        toBlur: () => dataTableRef.value?.toBlur(),
        toActive: () => dataTableRef.value?.toActive(),
        toResetActive: () => {
            dataTableRef.value?.resetCursor();
            dataTableRef.value?.toActive();
        },
        toFocus: () => {
            inputRef.value?.focus();
            dataTableRef.value?.toActive();
        },
        focusHandler: () => {
            dataTableRef.value?.toActive();
        },
        inputHandler,
        getActiveRowHandler: (row: any) => {
            curActiveRow.value = row;
        }
    };

    return {
        inputRef,
        dataTableRef,
        getDataByPage,
        getActiveRow,
        resetSearchParams,
        apiParams,
        data: dataTable.data,
        columns: dataTable.columns,
        summaryColumns: dataTable.summaryColumns,
        loading: dataTable.loading,
        pagination: dataTable.pagination,
        columnChecks: dataTable.columnChecks,
        ...methods
    };
}
